package ai.moran.demo.stateMachine.test;

import ai.moran.demo.entity.Door;
import ai.moran.demo.enums.TurnstileEvents;
import ai.moran.demo.enums.TurnstileStates;
import ai.moran.demo.exception.RRException;
import ai.moran.demo.service.DoorService;
import ai.moran.demo.vo.R;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Service;

/**
 * @author zhuhaitao
 * @email zhuhaitao@imoran.net
 * @date 2020/8/25 4:54 下午
 */
@Service
public class TurnstileStateMachineService {
    @Autowired
    private BeanFactory beanFactory;

    @Autowired
    private TurnstileStateMachineConfig turnstileStateMachineConfig;

    @Autowired
    private DoorService doorService;

    public R sendEvent(Integer id, TurnstileEvents events) {
        Door door=doorService.getById(id);
        if (null==door){
            return R.error("查询失败");
        }
        TurnstileStates currentStates = TurnstileStates.getByState(door.getState());
        if(null!=currentStates){
            StateMachine<TurnstileStates, TurnstileEvents> stateMachine = null;
            try {
                stateMachine = turnstileStateMachineConfig
                        .buildWithState(beanFactory, currentStates);
            } catch (Exception e) {
                throw new RRException("状态机创建失败");
            }
            stateMachine.start();
            Message<TurnstileEvents> eventsMessage = MessageBuilder
                    .withPayload(events)
                    .setHeader("taskId", id)
                    .build();
            if (!stateMachine.sendEvent(eventsMessage)) {
                return R.error("任务【" + id + "】当前状态为【" +currentStates + "】,不能触发【" + events + "】事件");
            }
            RuntimeException runtimeException = stateMachine.getExtendedState().get(RuntimeException.class, RuntimeException.class);
            if (runtimeException != null) {
                throw runtimeException;
            }
        }
        return R.ok();
    }
}
